use super::*;

/// A [Coverage Table](
/// https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-table).
#[derive(Debug, Clone, Copy)]
pub enum Coverage<'a> {
	Format1 {
		/// Array of glyph IDs. Sorted.
		glyphs: LazyArray16<'a, GlyphId>,
	},
	Format2 {
		/// Array of glyph ranges. Ordered by `RangeRecord.start`.
		records: LazyArray16<'a, RangeRecord>,
	},
}
impl<'a> FromSlice<'a> for Coverage<'a> {
	fn parse(data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		match s.read::<u16>()? {
			1 => Some(Self::Format1 {
				glyphs: s.parse_array16()?, //
			}),
			2 => Some(Self::Format2 {
				records: s.parse_array16()?,
			}),
			_ => None,
		}
	}
}
impl<'a> Coverage<'a> {
	/// Checks that glyph is present.
	pub fn contains(&self, glyph: GlyphId) -> bool {
		self.get(glyph).is_some()
	}
	/// Returns the coverage index of the glyph or `None` if it is not covered.
	pub fn get(&self, glyph: GlyphId) -> Option<u16> {
		match self {
			Self::Format1 { glyphs } => {
				glyphs.binary_search(&glyph).map(|p| p.0) //
			}
			Self::Format2 { records } => {
				let record = records.range(glyph)?;
				let offset = glyph.0 - record.start.0;
				record.value.checked_add(offset)
			}
		}
	}
}
impl<'a> IntoIterator for Coverage<'a> {
	type Item = (u16, GlyphId, GlyphId);
	type IntoIter = CoverageIter<'a>;
	fn into_iter(self) -> Self::IntoIter {
		CoverageIter { coverage: self, next: 0 }
	}
}
pub struct CoverageIter<'a> {
	coverage: Coverage<'a>,
	next: u16,
}
impl<'a> Iterator for CoverageIter<'a> {
	type Item = (u16, GlyphId, GlyphId);
	fn next(&mut self) -> Option<Self::Item> {
		match &self.coverage {
			Coverage::Format1 { glyphs } => {
				if let Some(ret) = glyphs.get(self.next) {
					self.next += 1;
					return Some((self.next - 1, ret, ret));
				}
				return None;
			}
			Coverage::Format2 { records } => {
				if let Some(r) = records.get(self.next) {
					self.next += 1;
					return Some((r.value, r.start, r.end));
				} else {
					return None;
				}
			}
		}
	}
}
